package com.jmp.autocofiguration.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.annotation.JSONField;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.CannedAccessControlList;
import com.aliyun.oss.model.CreateBucketRequest;
import com.aliyun.oss.model.PutObjectResult;
import com.jmp.autocofiguration.OneOssProperties;
import lombok.Builder;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import one.stand.enums.EnumUtil;
import one.stand.util.HttpUtil2;
import one.stand.util.SnowflakeIdWorker;
import org.apache.commons.lang3.StringUtils;

import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Objects;

/**
 * oss文件上传
 */
@Slf4j
public class OssUtil2 {
    private static SnowflakeIdWorker snowflakeIdWorker = new SnowflakeIdWorker(0, 0);
    private static OSSClient client;
    private static String websiteUrl;
    private static String websiteUrlReplace;
    private static String bucketName;

    public void init(OneOssProperties oneOssProperties) {
        bucketName = oneOssProperties.getBucketName();
        websiteUrl = oneOssProperties.getUrl();
        websiteUrlReplace = oneOssProperties.getUrlReplace();

        client = new OSSClient(oneOssProperties.getEndpoint(), oneOssProperties.getAccessKeyId(), oneOssProperties.getAccessKeySecret());
        // 判断容器是否存在,不存在就创建
        if (!client.doesBucketExist(bucketName)) {
            client.createBucket(bucketName);
            CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);
            createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead);
            client.createBucket(createBucketRequest);
        }
        client.setBucketAcl(bucketName, CannedAccessControlList.PublicRead);
    }

    public static String getWebsiteUrl() {
        return websiteUrl;
    }

    public static String getWebsiteUrlReplace(String url) {
        if (StringUtils.isBlank(url) || StringUtils.isBlank(websiteUrlReplace) || !StringUtils.contains(url, websiteUrlReplace))
            return url;

        return StringUtils.replaceAll(url, websiteUrlReplace, websiteUrl);
    }

    public static String uploadByFileName(InputStream inputStream, String fileName) {
        String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
        FileSuffix fileSuffix = FileSuffix.fromMap(suffix);
        return upload(inputStream, fileSuffix, false);
    }

    public static String upload(InputStream inputStream, String suffix) {
        FileSuffix fileSuffix = FileSuffix.fromMap(suffix);
        return upload(inputStream, fileSuffix, true);
    }

    public static String upload(InputStream inputStream, FileSuffix fileSuffix) {
        return upload(inputStream, fileSuffix, true);
    }

    public static String upload(InputStream inputStream, FileSuffix fileSuffix, boolean closeStream) {
        try {
            String fileUrl = getFilePath(fileSuffix);
            PutObjectResult result = client.putObject(bucketName, fileUrl, inputStream);
            if (result != null) {
                return websiteUrl + fileUrl;
            }
        } catch (Exception e) {
            log.error("上传Oss异常", e);
        } finally {
            if (closeStream) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    public static String upload(String fileUrl, InputStream inputStream) {
        PutObjectResult result = client.putObject(bucketName, fileUrl, inputStream);
        if (result != null) {
            return websiteUrl + fileUrl;
        }
        return null;
    }

    public static ImgInfo info(String imgUrl) {
        try {
            String result = HttpUtil2.get(imgUrl + "?x-oss-process=image/info");
            ImgInfoResult infoResult = JSON.parseObject(result, ImgInfoResult.class);
            return ImgInfo.builder()
                    .imageHeight(infoResult.getImageHeight().getValue())
                    .imageWidth(infoResult.getImageWidth().getValue())
                    .build();
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    private static String getFilePath(FileSuffix fileSuffix) {
        long date = System.currentTimeMillis();
        String dateStr = StringUtils.reverse(String.valueOf(date));

        String path = Objects.nonNull(fileSuffix) ? fileSuffix.getPath() : Path.other.getPath();

        return dateStr + "/" + path + "/" + snowflakeIdWorker.nextId() + "." + fileSuffix.getSuffix();
    }

    public enum FileSuffix {
        /**
         * photo
         **/
        jpg("jpg", Path.photo), png("png", Path.photo), jpeg("jpeg", Path.photo), gif("gif", Path.photo),
        /**
         * recording
         **/
        mp3("mp3", Path.recording),
        /**
         * video
         **/
        avi("avi", Path.video), mpg("mpg", Path.video), mlv("mlv", Path.video), mpe("mpe", Path.video), mpeg("mpeg", Path.video), dat("dat", Path.video), mp4("mp4", Path.video),
        /**
         * model
         **/
        zip("zip", Path.model), thirdD("3d", Path.model),
        ;

        private String suffix;
        private Path path;

        FileSuffix(String suffix, Path path) {
            this.suffix = suffix;
            this.path = path;
        }

        public String getSuffix() {
            return suffix;
        }

        public String getPath() {
            return path.getPath();
        }

        private static Map<String, FileSuffix> map = EnumUtil.getEnumMap(values(), FileSuffix::getSuffix);

        public static FileSuffix fromMap(String suffix) {
            return map.get(suffix.toLowerCase());
        }
    }

    public enum Path {
        photo("photo"),
        recording("recording"),
        video("video"),
        model("model"),
        other("other"),
        ;

        private String path;

        Path(String path) {
            this.path = path;
        }

        public String getPath() {
            return path;
        }
    }

    @Data
    @Builder
    public static class ImgInfo {
        private Integer imageHeight;
        private Integer imageWidth;
    }

    @Data
    public static class ImgInfoResult {
        @JSONField(name = "ImageHeight")
        private Value imageHeight;
        @JSONField(name = "ImageWidth")
        private Value imageWidth;
    }

    @Data
    public static class Value {
        @JSONField(name = "Value")
        private Integer value;
    }
}
